
const lodash = require('lodash')
const { existsSync } = require('fs-extra')

const pageFns = {}

pageFns.delay = (ms) => {
    return new Promise((resolve) => setTimeout(resolve, ms));
}

pageFns.close = async (browser, ms) => {
    await browser.close()
    await pageFns.delay(ms)
}

pageFns.tryCatch = async (page, bizFun, setting) => {
    return await pageFns.deepRetry(["goto"], page, bizFun, setting)
}

pageFns.deepRetry = async (args, page, bizFun, setting) => {
    try {
        if (setting) {
            if (setting.timeout) {
                setting.default = await setting.page.getDefaultTimeout()
                await setting.page.setDefaultTimeout(setting.timeout)
            }
            if (setting.wait) {
                await pageFns.delay(setting.wait)
            }
        }
        let result = await bizFun(args[0], page, setting)
        if (setting) {
            if (setting.timeout) {
                await setting.page.setDefaultTimeout(setting.default)
            }
            if (setting.wait) {
                await pageFns.delay(setting.wait)
            }
        }
        return { err: null, data: result }
    } catch (err) {
        args = args.slice(1)
        if (args.length < 1) {
            return { err: err, data: null }
        }
        if (setting) {
            if (setting.wait) {
                await pageFns.delay(setting.wait)
            }
            setting.err = err
        }
        return await pageFns.deepRetry(args, page, bizFun, setting)
    }
}

pageFns.runResetTimout = async (args, page, bizFun, setting) => {
    try {
        if (setting.timeout) {
            setting.default = await page.getDefaultTimeout()
        }
        await page.setDefaultTimeout(setting.timeout)
        let result = await bizFun(args, page)
        if (setting.timeout) {
            await page.setDefaultTimeout(setting.default)
        }
        return result
    } catch (err) {
        return { err: err, data: null }
    }
}

pageFns.fileUpload = async ({ page, element, files }) => {
    const newFiles = files.map((file) => {
        const filePattern = /(jpg|jpeg|png|webp|mp4)/gi.test(file)
        const fileExitst = existsSync(file)
        if (!filePattern) return new TypeError('File image is not support')
        if (!fileExitst) return new Error(`File image is not exitst ${file}`)
        return file
    })
    await page.waitForSelector(`${element}`)
    const input = await page.$(`${element}`)
    const filesUpload = await Promise.all([...newFiles])
    await input.uploadFile(...filesUpload)
}

pageFns.attributeName = async (page, selector, attributeName) => {
    return await page.evaluate((selector, attributeName) => {
        const element = document.querySelector(selector);
        return element ? element.getAttribute(attributeName) : null;
    }, selector, attributeName);
}

pageFns.attributeNames = async (page, selector, attributeName) => {
    const attributeValues = await page.evaluate((selector, attributeName) => {
        const elements = Array.from(document.querySelectorAll(selector))
        return elements.map(element => {
            return element.getAttribute(attributeName)
        })
    }, selector, attributeName);
    return attributeValues
}

pageFns.getText = async (page, selector) => {
    return await page.evaluate((selector) => {
        const e = document.querySelector(selector)
        return e ? e.textContent : null
    }, selector)
}

pageFns.isSelExist = async (page, selector) => {
    let element = await page.$(selector)
    if (element != null) {
        return true
    }
    return false
}

pageFns.waitAndClick = async (page, selector) => {
    await page.waitForSelector(selector)
    await page.click(selector)
}

pageFns.waitAndTap = async (page, selector) => {
    await page.waitForSelector(selector)
    await page.tap(selector)
}

pageFns.waitDisappear = async (page, selector) => {
    await page.waitForFunction((selector) => {
        return !document.querySelector(selector);
    }, {}, selector);
}

pageFns.waitDidappear = async (page, selector) => {
    await page.waitForFunction((selector) => {
        return !!document.querySelector(selector);
    }, {}, selector);
}

pageFns.waitAttrDidappear = async (page, selector, attr) => {
    await page.waitForFunction((selector, attr) => {
        const element = document.querySelector(selector);
        return element && element.hasAttribute(attr) === true;
    }, {}, selector, attr);
}

pageFns.waitAttrDisappear = async (page, selector, attr) => {
    await page.waitForFunction((selector, attr) => {
        const element = document.querySelector(selector);
        return element && element.hasAttribute(attr) === false;
    }, {}, selector, attr);
}

pageFns.getIframePage = async (page, url) => {
    await page.waitForSelector('iframe')
    let frame = await page.waitForFrame(async (frame) => {
        return frame.url() == url
    })
    return frame
}

pageFns.overridePermissions = async (page, url) => {
    await page.browserContext().overridePermissions(url, ['geolocation', 'notifications'])
}


export { pageFns }